<template>
  <div id='canvas-box'>
    <div class="filter-box" style="margin-left: 20px">
      <div class="filter-left">
        <span>时间：</span>
        <el-date-picker
            v-model="timeValue"
            value-format="yyyy-MM-dd HH:mm:ss"
            size="mini"
            type="datetimerange"
            start-placeholder="开始日期"
            range-separator="至"
            end-placeholder="结束日期"
            :picker-options="pickerOptions"
            align="left"
        >
        </el-date-picker>
        <span style="margin-left: 10px">标签：</span>
        <el-select v-model="tagId" size="mini" placeholder="请选择" clearable>
          <el-option
              v-for="(item,index) in tagOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id">
          </el-option>
        </el-select>
        <el-button type="primary" size="mini" :disabled="!tagId" @click="onSearch" style="margin:0 12px;"><i
            class="el-icon-search"></i>查询
        </el-button>
        <el-button type="primary" size="mini" @click="onReset" style="margin:0;"><i
            class="el-icon-refresh"></i>重置
        </el-button>
      </div>
    </div>
    <div class='filter-box topology-tool'>
      <div class='filter-left'>
        <i style='margin:0 10px'></i>
        <span>缩放：</span>
        <el-tooltip class='item' effect='dark' content='放大' placement='top'>
          <i class='el-icon-zoom-in' @click='onZoomIn'></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='缩小' placement='top'>
          <i class='el-icon-zoom-out' @click='onZoomOut'></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <span>移动：</span>
        <el-tooltip class='item' effect='dark' content='左移' placement='top'>
          <i class='el-icon-back' @click="onMove('left')"></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='上移' placement='top'>
          <i class='el-icon-top' @click="onMove('top')"></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='下移' placement='top'>
          <i class='el-icon-bottom' @click="onMove('bottom')"></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='右移' placement='top'>
          <i class='el-icon-right' @click="onMove('right')"></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <span>当前速率：</span>
        <span style='margin:0 10px'>{{ animate.animateSpan }}px/s</span>
        <el-tooltip class='item' effect='dark' content='慢' placement='top'>
          <i class='el-icon-d-arrow-left' @click='onBackward'></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='快' placement='top'>
          <i class='el-icon-d-arrow-right' @click='onForward'></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <span>播发设置：</span>
        <el-tooltip class='item' effect='dark' content='播放' placement='top'>
          <i class='el-icon-video-play' @click='onPlay'></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='暂停' placement='top'>
          <i class='el-icon-video-pause' @click='onPause'></i>
        </el-tooltip>
        <i style='margin:0 10px'></i>
        <el-tooltip class='item' effect='dark' content='重置' placement='top'>
          <i class='el-icon-refresh' @click='onRefresh'></i>
        </el-tooltip>

      </div>
      <div class='filter-right'>

      </div>
    </div>
    <div class='canvas-box'>
      <div class='canvas-wrapper'
           :style="{backgroundSize: bgSize + '%' + ' ' + bgSize + '%',backgroundPosition: -bgPositionX + 'px' + ' ' + -bgPositionY + 'px'}">
        <div id='topology-canvas' style="overflow:hidden;"></div>
      </div>
    </div>
  </div>
</template>
<script>
import {getTackHistoryByTag} from '@/api/track'
import {getCommonList} from '@/api/common'
import {formatDate} from '@/utils/validate'
import {Topology, Node, Line, Point} from '@topology/core'
import {register as registerActivity} from '@topology/activity-diagram'
import {getHistoryNodes, getLines} from './tools'
// 配置项
const canvasOptions = {
  font: {
    color: '#fff',
    fontSize: 12
  },
  // 连线颜色
  color: '#fff',
  keydown: -1,
  disableEmptyLine: true,
  disableScale: true,
  maxScale: 2,
  autoAnchor: false,
  autoExpandDistance: 0
}
export default {
  data() {
    return {
      // 时间选择
      tagId: '',
      timeValue: [],
      pickerOptions: {
        shortcuts: [
          {
            text: '最近一小时',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000)
              picker.$emit('pick', [start, end])
            }
          },
          {
            text: '最近两小时',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000 * 2)
              picker.$emit('pick', [start, end])
            }
          },
          {
            text: '最近四小时',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000 * 4)
              picker.$emit('pick', [start, end])
            }
          },
          {
            text: '最近一周',
            onClick(picker) {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
              picker.$emit('pick', [start, end])
            }
          }
        ]
      },
      tagOptions: [],
      //
      canvas: null,
      bgSize: 100,
      width: 1200,
      height: 600,
      bgPositionX: 0,
      bgPositionY: 0,
      direction: {
        x: 0,
        y: 0
      },
      animate: {
        animateType: 'flow',
        animateCycle: 1,
        animateColor: 'green',
        animateSpan: 32
      },
      lineIds: [],
      curIndex: 0,
      // 暂停
      isPause: true,
      isRefresh: false
    }
  },
  created() {
    this.setTime()
    registerActivity()
    // this.$startLoading()
    getCommonList('relTag').then(res => {
      // this.$endLoading()
      if (res.status !== 200) return this.$msgPrompt.error(res.msg)
      this.tagOptions = res.obj
    })
  },
  mounted() {
    this.initCanvas()
  },
  methods: {
    setTime() {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
      this.timeValue = [start, end]
      this.timeValue.forEach((item, index) => {
        this.timeValue[index] = formatDate(item.getTime())
      })
    },
    getData() {
      if (!this.timeValue) {
        this.timeValue = []
      }
      let {tagId, timeValue} = this
      console.log(timeValue)
      getTackHistoryByTag({tagId, startTime: timeValue[0], endTime: timeValue[1]})
          .then((res) => {
            if (res.status !== 200) return this.$msgPrompt.error(res.msg)
            if (res.obj && res.obj.length) {
              getHistoryNodes(res.obj).forEach((node, index) => {
                this.canvas.addNode(new Node(node), false)
              })
              this.onUpdateLines()
              this.canvas.render()
              this.setAnimate()
            }
          })
          .catch(() => {
            this.loading = false
          })
    },
    getBasData() {
      let points = []
      for (let i = 0; i < 10; i++) {
        let ipx = Math.round(Math.random() * 1000)
        let ipy = Math.round(Math.random() * 600)
        points.push({x: ipx, y: ipy})
      }
      getHistoryNodes(points).forEach((node, index) => {
        this.canvas.addNode(new Node(node), false)
      })
      this.onUpdateLines()
      // console.log(this.canvas.getRect().center)
      this.canvas.render()
      this.setAnimate()
    },
    initCanvas() {
      this.canvas = null
      canvasOptions.on = this.onMessage
      this.canvas = new Topology('topology-canvas', canvasOptions)
      this.getBasData()
    },
    setAnimate() {
      this.canvas.data.pens.forEach((line, index) => {
        if (line.type == 1) {
          line.tags.push(line.id)
          this.lineIds.push(line.id)
          // 1. 设置动画类型，空（默认），beads（水珠流动）， dot（圆点）， comet（彗星）
          line.animateType = this.animate.animateType
          // 2. 动画颜色
          line.animateColor = this.animate.animateColor
          line.animateCycle = 1
          // 3. 动画移动大小
          line.animateSpan = this.animate.animateSpan
        } else {
          line.locked = 2
        }
      })
      console.log(this.lineIds)
    },
    onMessage(event, data) {
      console.log(event, data)
      // 右侧输入框编辑状态时点击编辑区域其他元素，onMessage执行后才执行onUpdateProps方法，通过setTimeout让onUpdateProps先执行
      setTimeout(() => {
        switch (event) {
          case 'anchor':
            this.curAnchorNode = data.node
            break
          case 'node':
            console.log(data.rect)
            console.log(data.rect.x, data.rect.y)

          case 'moveInNode':
            break
          case 'moveOutNode':
            break
          case 'addNode':
            this.props = {
              node: data,
              line: null,
              multi: false,
              expand: null,
              nodes: null,
              locked: data.locked
            }
            break
          case 'delete':
            break
          case 'dblclick':
            break
          case 'line':
          case 'addLine':
            break
          case 'animateEnd':
            console.log(this.curIndex)
            if (this.isPause || this.isRefresh) {
              break
            }
            this.canvas.data.pens.forEach(pen => {
              if (pen.type == 1) {
                if (pen.from.id == data.data.from.id && pen.to.id == data.data.to.id) {
                  pen.strokeStyle = this.animate.animateColor
                  pen.locked = 2
                  this.canvas.updateProps(pen)
                }
              }
            })
            if (this.curIndex < (this.lineIds.length - 1)) {
              this.curIndex++
              this.canvas.find(this.lineIds[this.curIndex]).animateStart = Date.now()
              this.canvas.animate()
            } else {
              this.isPause = true
            }
            break
          case 'multi':
            this.props = {
              node: data.length === 1 ? data[0] : null,
              line: null,
              multi: data.length > 1 ? true : false,
              nodes: data.length > 1 ? data : null,
              locked: this.getLocked({nodes: data})
            }
            break
          case 'space':
            this.props = {
              node: null,
              line: null,
              multi: false,
              nodes: null,
              locked: false
            }
            break
          case 'moveOut':
            break
          case 'move':
            break
          case 'resizeNodes':
            if (data.length > 1) {
              this.props = {
                node: null,
                line: null,
                multi: true,
                nodes: data,
                locked: this.getLocked({nodes: data})
              }
            } else {
              this.props = {
                node: data[0],
                line: null,
                multi: false,
                nodes: null,
                locked: false
              }
            }
            break
          case 'resize':
          case 'scale':
          case 'locked':
            break
          case 'moveInLine':
            // 获取 链接节点id ，通过canvas.data.pens 获取对应节点拿到所存储数据
            break
        }
      }, 0)
    },
    onSearch() {
      this.canvas.open({pens: []})
      this.bgSize = 100
      this.width = 1200
      this.height = 600
      this.bgPositionX = 0
      this.bgPositionY = 0
      this.direction = {
        x: 0,
        y: 0
      }
      this.animate = {
        animateType: 'flow',
        animateCycle: 1,
        animateColor: 'red',
        animateSpan: 32
      }
      this.lineIds = []
      this.curIndex = 0
      // 暂停
      this.isPause = true
      this.isRefresh = false
      this.getData()
    },
    onReset() {
      this.tagId = ''
      this.setTime()
    },
    onZoomIn() {
      if (!this.canvas) return this.$msgPrompt.warning('人员轨迹不存在')
      this.canvas.translate(-((this.width * this.canvas.data.scale - this.width) / 2 - this.bgPositionX), -((this.height * this.canvas.data.scale - this.height) / 2 - this.bgPositionY))
      this.bgPositionX = (this.width * this.canvas.data.scale - this.width) / 2
      this.bgPositionY = (this.height * this.canvas.data.scale - this.height) / 2
      if (this.bgSize >= 200) {
        this.bgSize = 200
      } else {
        this.bgSize += 10
        let scale = Math.floor(this.canvas.data.scale * 100)
        scale += 10
        this.bgPositionX = (this.width * scale / 100 - this.width) / 2
        this.bgPositionY = (this.height * scale / 100 - this.height) / 2
        this.canvas.scaleTo(scale / 100, new Point(this.width / 2, this.height / 2))
      }

    },
    onZoomOut() {
      if (!this.canvas) return this.$msgPrompt.warning('人员轨迹不存在')
      if (this.bgSize <= 100) {
        this.bgSize = 100
      } else {
        this.canvas.translate(-((this.width * this.canvas.data.scale - this.width) / 2 - this.bgPositionX), -((this.height * this.canvas.data.scale - this.height) / 2 - this.bgPositionY))
        this.bgPositionX = (this.width * this.canvas.data.scale - this.width) / 2
        this.bgPositionY = (this.height * this.canvas.data.scale - this.height) / 2
        this.bgSize -= 10
        let scale = Math.floor(this.canvas.data.scale * 100)
        scale -= 10
        this.bgPositionX = (this.width * scale / 100 - this.width) / 2
        this.bgPositionY = (this.height * scale / 100 - this.height) / 2
        this.canvas.scaleTo(scale / 100, new Point(this.width / 2, this.height / 2))
      }

    },
    onMove(direction) {
      switch (direction) {
        case 'left':
          console.log(this.bgPositionX)
          if (this.bgPositionX <= 20) {
            this.direction.x += this.bgPositionX
            this.canvas.translate(this.bgPositionX, 0)
            this.bgPositionX = 0
          } else {
            this.bgPositionX -= 20
            this.direction.x += 20
            this.canvas.translate(20, 0)
          }
          break
        case 'top':
          if (this.bgPositionY <= 20) {
            this.direction.y += this.bgPositionY
            this.canvas.translate(0, this.bgPositionY)
            this.bgPositionY = 0
          } else {
            this.bgPositionY -= 20
            this.direction.y += 20
            this.canvas.translate(0, 20)
          }
          break
        case 'right':
          let lenR = this.width * this.canvas.data.scale - this.width - this.bgPositionX
          if (lenR <= 20) {
            this.direction.x -= lenR
            this.canvas.translate(-lenR, 0)
            this.bgPositionX = this.width * this.canvas.data.scale - this.width
          } else {
            this.bgPositionX += 20
            this.direction.x -= 20
            this.canvas.translate(-20, 0)
          }
          break
        case 'bottom':
          let len = this.height * this.canvas.data.scale - this.height - this.bgPositionY
          console.log(len)
          if (len <= 20) {
            this.direction.y -= len
            this.canvas.translate(0, -len)
            this.bgPositionY = this.height * this.canvas.data.scale - this.height
          } else {
            this.bgPositionY += 20
            this.direction.y -= 20
            this.canvas.translate(0, -20)
          }
          break
      }
    },
    // 快退
    onBackward() {
      if (!this.isPause) return this.$msgPrompt.warning('请先暂停播放')
      if (this.animate.animateSpan <= 1) return
      this.isPause = true
      if (this.animate.animateSpan == 4) {
        this.animate.animateSpan -= 3
      } else {
        this.animate.animateSpan -= 4
      }
      this.canvas.data.pens.forEach((line, index) => {
        if (line.type == 1) {
          // 动画移动大小
          line.animateSpan = this.animate.animateSpan
          line.strokeStyle = this.animate.animateColor
          line.locked = 0
          this.canvas.updateProps(line)
        }
      })
    },
    // 快进
    onForward() {
      if (!this.isPause) return this.$msgPrompt.warning('请先暂停播放')
      if (this.animate.animateSpan >= 64) return
      this.isPause = true
      if (this.animate.animateSpan == 1) {
        this.animate.animateSpan += 3
      } else {
        this.animate.animateSpan += 4
      }
      this.canvas.data.pens.forEach((line, index) => {
        if (line.type == 1) {
          // 动画移动大小
          line.animateSpan = this.animate.animateSpan
        }
      })
    },
    onPlay() {
      console.log(this.curIndex, this.lineIds)
      if (!this.lineIds.length) return this.$msgPrompt.warning('暂无人员轨迹')
      if (this.curIndex == (this.lineIds.length - 1)) return this.$msgPrompt.warning('轨迹播放已结束')
      this.isRefresh = false
      this.isPause = false
      // 2.A 设置开始播放属性（为当前时间）
      this.canvas.find(this.lineIds[this.curIndex]).animateStart = Date.now()
      this.canvas.animate()
    },
    onPause() {
      if (!this.lineIds.length) return this.$msgPrompt.warning('暂无人员轨迹')
      if (this.curIndex == (this.lineIds.length - 1)) return this.$msgPrompt.warning('轨迹播放已结束')
      this.isPause = true
      this.canvas.find(this.lineIds[this.curIndex]).animateStart = 0
      this.canvas.updateProps(this.canvas.find(this.lineIds[this.curIndex]))

    },
    onRefresh() {
      if (!this.lineIds.length) return this.$msgPrompt.warning('暂无人员轨迹')
      this.canvas.find(this.lineIds[this.curIndex]).animateStart = 0
      this.isPause = true
      this.isRefresh = true
      this.canvas.data.pens.forEach((line, index) => {
        if (line.type == 1) {
          // 动画移动大小
          line.animateStart = 0
          line.animateSpan = 32
          line.strokeStyle = 'transparent'
          line.locked = 0
          this.canvas.updateProps(line)
        }
      })
      this.animate.animateSpan = 32
      this.curIndex = 0
    },
    updateNodePositions() {
      this.canvas.data.pens.forEach(pen => {
        // 节点 随之平移相对位置 保持与图片等比缩放
        if (pen.type == 0) {
          pen.rect.x = Math.floor(pen.data.x * (this.bgSize / 100))
          pen.rect.y = Math.floor(pen.data.y * (this.bgSize / 100))
          pen.rect.width = Math.floor(pen.data.width * (this.bgSize / 100))
          pen.rect.height = Math.floor(pen.data.height * (this.bgSize / 100))
          console.log(pen.rect.x, pen.rect.y)
          this.canvas.updateProps(pen)
        }
      })
    },
    onUpdateLines() {
      for (let i = 0; i < this.canvas.data.pens.length; i++) {
        if (this.canvas.data.pens[i].type === 1) {
          this.canvas.data.pens.splice(i, 1)
          i--
        }
      }
      let arr = []
      this.canvas.data.pens.forEach((node, index) => {
        if (index < this.canvas.data.pens.length - 1) {
          console.log(node)
          let fromNode = node.anchors.filter(i => i.direction == 2)[0]
          let toNode = this.canvas.data.pens[index + 1].anchors.filter(i => i.direction == 4)[0]
          arr.push({
            from: {
              x: fromNode.x,
              y: fromNode.y,
              anchorIndex: fromNode.direction,
              id: node.id
            },
            to: {
              x: toNode.x,
              y: toNode.y,
              anchorIndex: toNode.direction,
              id: this.canvas.data.pens[index + 1].id
            },
            strokeStyle: 'transparent'
          })
        }
      })
      console.log(arr)
      getLines(arr).forEach(item => {
        let line = new Line(item)
        this.canvas.addLine(line)
        line.calcControlPoints()
      })
    },
    getLocked(data) {
      console.log('锁定', data)
      let locked = true
      if (data.nodes && data.nodes.length) {
        for (const item of data.nodes) {
          if (!item.locked) {
            locked = false
            break
          }
        }
      }
      if (locked && data.lines) {
        for (const item of data.lines) {
          if (!item.locked) {
            locked = false
            break
          }
        }
      }
      console.log(locked)
      return locked
    }
  }
}
</script>

<style lang='scss' scoped>
#canvas-box {
  background-color: #fff;
  margin: 0 10px;
  padding: 10px;
  min-width: 1250px;
  min-height: 650px;
  overflow: auto;
  display: flex;
  flex-direction: column;
}

.canvas-box {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.canvas-wrapper {
  width: 1200px;
  height: 600px;
  background-image: url("../../assets/track/bg.png");
  background-repeat: no-repeat;
  border: 1px solid #000000;
}

#topology-canvas {
  width: 100%;
  height: 100%;
}

.topology-tool {
  i {
    font-size: 18px;
  }
}
</style>
